package org.chispa.api.visitors;

import java.util.List;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.chispa.api.hashers.IndexingHash;
import org.chispa.api.query.ParamWrapper;
import org.chispa.api.util.BadSyntaxException;
import org.chispa.api.util.ExpressionLanguage;
import org.chispa.api.util.NoSuitableVisitorException;

class StringParamVisitor extends SingleParamVisitor<String,String> {
	
	private IndexingHash<String,String> hasher;
	
	public StringParamVisitor(Cipher blockCipher,SecretKeySpec spec,IvParameterSpec ivSpec,IndexingHash<String,String> hasher)
	{
		super(blockCipher, spec,ivSpec);
		this.hasher=hasher;
	}

	@Override
	public String visitEncrypt(ParamWrapper<String,String,String> wrap) {
		String parameter=wrap.getWrappedParam();
		try {
			return doEncrypt(parameter.getBytes());
		} catch (Exception e) {
			System.err.println(e.getLocalizedMessage());
			return parameter;
		}
	}

	@Override
	public String visitHash(ParamWrapper<String,String,String> wrap) throws NoSuitableVisitorException {
		try {
			return ExpressionLanguage.quote(hasher.computeHash(wrap.getWrappedParam()));
		} catch (NoSuitableVisitorException e) {
			throw new NoSuitableVisitorException(e);
		}
	}
	
	IndexingHash<?,?> getHasher()
	{
		return hasher;
	}

	@Override
	public String visitHashExpr(ParamWrapper<String, String,String> wrap,Map<String,String>params) throws BadSyntaxException, NoSuitableVisitorException {
		String fromValue=wrap.getWrappedParam();
		List<String> list=ExpressionLanguage.evaluateTextual(fromValue);
		for(String text:list)
		{
			if(text.length()<2)
				throw new BadSyntaxException("The value must be at least 2 characters long!");
			String replace=ExpressionLanguage.quote(hasher.computeHash(text));
			fromValue=ExpressionLanguage.escapeFromJava(fromValue).replace(ExpressionLanguage.quote(text), replace);
		}
		return fromValue.replaceAll("\"\"","\"");
	}

	@Override
	public String visitDecrypt(String encrypted) {
			return doDecrypt(encrypted);
	}

}
